package com.arsl.client.view;

import java.util.HashMap;

import com.arsl.client.GlobalInfo;
import com.arsl.client.data.Edition;
import com.arsl.client.data.Paper;
import com.arsl.client.data.Section;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Widget;

public class ManagePaperView extends Composite {

	@UiField
	ListBox lstPaper;

	@UiField
	TextBox txtHeight;

	@UiField
	TextBox txtWidth;

	@UiField
	TextBox txtNewSection;

	@UiField
	Button btnAddNewSection;

	@UiField
	ListBox lstSections;

	@UiField
	Button btnRemoveSection;

	@UiField
	TextBox txtNewEdition;

	@UiField
	Button btnAddNewEdition;

	@UiField
	ListBox lstEditions;

	@UiField
	Button btnRemoveEdition;

	@UiField
	Button btnOk;

	@UiField
	Button btnReset;

	private int paperId;

	private Paper[] papers;

	private HashMap<Integer, Edition[]> paperToEditionMap;
	private HashMap<Integer, Section[]> paperToSectionMap;

	private boolean changeMade = false;

	private Paper selectedPaper;

	private static ManagePaperViewUiBinder uiBinder = GWT
			.create(ManagePaperViewUiBinder.class);

	interface ManagePaperViewUiBinder extends UiBinder<Widget, ManagePaperView> {
	}

	public ManagePaperView() {
		initWidget(uiBinder.createAndBindUi(this));
		paperToEditionMap = new HashMap<Integer, Edition[]>();
		paperToSectionMap = new HashMap<Integer, Section[]>();
		initChanges();
	}

	private void initChanges() {
		changeMade = false;
	}

	@UiHandler("lstPaper")
	public void onSelectPaper(ChangeEvent event) {

		if (changeMade) {
			if (Window
					.confirm("There are unchanged modifications for this paper. Press ok to save the changes")) {
				saveChanges();
			}

		}

		setSelectedPaper();
		initChanges();
		updatePaperDetails();
	}

	private void setSelectedPaper() {
		selectedPaper = papers[lstPaper.getSelectedIndex()];
	}

	@UiHandler("txtHeight")
	public void onChangeHeight(ChangeEvent event) {
		changeMade = true;

	}

	@UiHandler("txtWidth")
	public void onChangeWidth(ChangeEvent event) {
		changeMade = true;
	}

	@UiHandler("btnRemoveSection")
	public void onRemoveSection(ClickEvent event) {
		int index = lstSections.getSelectedIndex();
		String removedSection = lstSections.getItemText(index);
		changeMade = true;
		lstSections.removeItem(index);
	}

	@UiHandler("btnRemoveEdition")
	public void onRemoveEdition(ClickEvent event) {
		int index = lstEditions.getSelectedIndex();
		String removedEdition = lstEditions.getItemText(index);
		changeMade = true;
		lstEditions.removeItem(index);
	}

	@UiHandler("btnAddNewSection")
	public void onAddNewSection(ClickEvent event) {
		String newSectionName = txtNewSection.getText().trim();
		if ("".equals(newSectionName)) {
			Window.alert("Section name cannot be empty");
			return;
		}
		if (isSectionNameExists(getSelectedPaper().getId(), newSectionName)) {
			Window.alert("Section name already exists");
			return;
		}
		changeMade = true;
		lstSections.addItem(newSectionName);
		txtNewSection.setText("");
	}

	@UiHandler("btnAddNewEdition")
	public void onAddNewEdition(ClickEvent event) {
		String newEditionName = txtNewEdition.getText().trim();
		if ("".equals(newEditionName)) {
			Window.alert("Edition name cannot be empty");
			return;
		}
		if (isEditionNameExists(getSelectedPaper().getId(), newEditionName)) {
			Window.alert("Edition name already exists");
			return;
		}
		changeMade = true;
		lstEditions.addItem(newEditionName);
		txtNewEdition.setText("");
	}

	private boolean isSectionNameExists(int paperId, String newSectionName) {
		for (int i = 0; i < lstSections.getItemCount(); i++) {
			if (lstSections.getItemText(i).equalsIgnoreCase(newSectionName)) {
				return true;
			}
		}
		return false;
	}

	private boolean isEditionNameExists(int paperId, String newEditionName) {
		for (int i = 0; i < lstEditions.getItemCount(); i++) {
			if (lstEditions.getItemText(i).equalsIgnoreCase(newEditionName)) {
				return true;
			}
		}
		return false;
	}

	public void loadPapers(Paper[] papers) {
		lstPaper.clear();
		this.papers = papers;
		for (int i = 0; i < papers.length; i++) {
			lstPaper.addItem(papers[i].getName(),
					String.valueOf(papers[i].getId()));
		}
		setSelectedPaper();
		updatePaperDetails();

	}

	private void updatePaperDetails() {
		final Paper paper = getSelectedPaper();
		final int paperId = paper.getId();
		txtHeight.setText(paper.getHeight() + "");
		txtWidth.setText(paper.getWidth() + "");

		GlobalInfo.rpcService.getEditions(paperId,
				new AsyncCallback<Edition[]>() {

					@Override
					public void onSuccess(Edition[] result) {
						setEditions(result);
						GlobalInfo.rpcService.getSections(paperId,
								new AsyncCallback<Section[]>() {

									@Override
									public void onSuccess(Section[] result) {
										setSections(result);
									}

									@Override
									public void onFailure(Throwable caught) {
										// TODO Auto-generated method stub
										caught.printStackTrace();
									}
								});
					}

					@Override
					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}
				});

	}

	public void setEditions(Edition[] editions) {
		lstEditions.clear();
		paperToEditionMap.put(getSelectedPaper().getId(), editions);
		for (int i = 0; i < editions.length; i++) {
			lstEditions.addItem(editions[i].getName(),
					String.valueOf(editions[i].getId()));
		}
	}

	public void setSections(Section[] sections) {
		lstSections.clear();
		paperToSectionMap.put(getSelectedPaper().getId(), sections);
		for (int i = 0; i < sections.length; i++) {
			lstSections.addItem(sections[i].getName(),
					String.valueOf(sections[i].getId()));
		}
	}

	private Paper getSelectedPaper() {
		return selectedPaper;
	}

	@UiHandler("btnReset")
	public void onReset(ClickEvent event) {
		updatePaperDetails();
		initChanges();
	}

	@UiHandler("btnOk")
	public void onOk(ClickEvent event) {
		saveChanges();
	}

	private void saveChanges() {
		if (!changeMade) {
			Window.alert("No changes to commit");
			return;
		}

		if (!Float.toString(getSelectedPaper().getHeight()).equals(
				txtHeight.getText())
				|| !Float.toString(getSelectedPaper().getWidth()).equals(
						txtWidth.getText())) {
			// changeDimensions

			GlobalInfo.rpcService.changeDimensions(getSelectedPaper().getId(),
					Float.parseFloat(txtWidth.getText()),
					Float.parseFloat(txtHeight.getText()),
					new AsyncCallback<Boolean>() {

						@Override
						public void onSuccess(Boolean result) {
							// TODO Auto-generated method stub

						}

						@Override
						public void onFailure(Throwable caught) {
							// TODO Auto-generated method stub

						}
					});
		}

		addSections();
		addEditions();
		removeSections();
		removeEditions();
		Window.alert("Changes committed successfully!");

	}

	private void addEditions() {

		boolean editionExists;
		Edition[] editions = paperToEditionMap.get(getSelectedPaper().getId());
		for (int i = 0; i < lstEditions.getItemCount(); i++) {
			editionExists = false;
			for (Edition edition : editions) {
				if (edition.getName().equalsIgnoreCase(
						lstEditions.getItemText(i))) {
					editionExists = true;
					break;
				}
			}
			if (!editionExists) {
				GlobalInfo.rpcService.addEdition(getSelectedPaper().getId(),
						lstEditions.getItemText(i),
						new AsyncCallback<Integer>() {

							@Override
							public void onSuccess(Integer newId) {
								if (newId <= 0) {
									Window.alert("Addding editions failed");
								}
							}

							@Override
							public void onFailure(Throwable caught) {
								// TODO Auto-generated method stub

							}
						});
			}
		}

	}

	private void addSections() {

		boolean sectionExists;
		Section[] sections = paperToSectionMap.get(getSelectedPaper().getId());
		for (int i = 0; i < lstSections.getItemCount(); i++) {
			sectionExists = false;
			for (Section section : sections) {
				if (section.getName().equalsIgnoreCase(
						lstSections.getItemText(i))) {
					sectionExists = true;
					break;
				}
			}
			if (!sectionExists) {
				GlobalInfo.rpcService.addSection(getSelectedPaper().getId(),
						lstSections.getItemText(i),
						new AsyncCallback<Integer>() {

							@Override
							public void onSuccess(Integer newId) {
								if (newId <= 0) {
									Window.alert("Addding sections failed");
								}
							}

							@Override
							public void onFailure(Throwable caught) {
								// TODO Auto-generated method stub

							}
						});
			}
		}

	}

	private void removeEditions() {
		boolean editionExists;
		Edition[] editions = paperToEditionMap.get(getSelectedPaper().getId());
		for (Edition edition : editions) {
			editionExists = false;
			for (int i = 0; i < lstEditions.getItemCount(); i++) {
				if (edition.getName().equalsIgnoreCase(
						lstEditions.getItemText(i))) {
					editionExists = true;
					break;
				}
			}
			if (!editionExists) {
				GlobalInfo.rpcService.removeEdition(getSelectedPaper().getId(),
						edition.getName(), new AsyncCallback<Boolean>() {

							@Override
							public void onSuccess(Boolean success) {
								if (!success) {
									Window.alert("Removing editions failed");
								}
							}

							@Override
							public void onFailure(Throwable caught) {
								// TODO Auto-generated method stub

							}
						});
			}
		}

	}

	private void removeSections() {
		boolean sectionExists;
		Section[] sections = paperToSectionMap.get(getSelectedPaper().getId());
		for (Section section : sections) {
			sectionExists = false;
			for (int i = 0; i < lstSections.getItemCount(); i++) {
				if (section.getName().equalsIgnoreCase(
						lstSections.getItemText(i))) {
					sectionExists = true;
					break;
				}
			}
			if (!sectionExists) {
				GlobalInfo.rpcService.removeSection(getSelectedPaper().getId(),
						section.getName(), new AsyncCallback<Boolean>() {

							@Override
							public void onSuccess(Boolean success) {
								if (!success) {
									Window.alert("Removing sections failed");
								}
							}

							@Override
							public void onFailure(Throwable caught) {
								// TODO Auto-generated method stub

							}
						});
			}
		}
	}

}
